package com.example.student.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.student.entity.SysNotification;
import com.example.student.entity.SysUser;
import com.example.student.entity.SysUserNotification;
import com.example.student.exception.BusinessException;
import com.example.student.mapper.SysNotificationMapper;
import com.example.student.mapper.SysUserMapper;
import com.example.student.mapper.SysUserNotificationMapper;
import com.example.student.model.NotificationVO;
import com.example.student.model.PageResult;
import com.example.student.service.NotificationService;
import com.example.student.util.SecurityUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class NotificationServiceImpl implements NotificationService {

    @Resource
    private SysNotificationMapper notificationMapper;
    
    @Resource
    private SysUserMapper userMapper;
    
    @Resource
    private SysUserNotificationMapper userNotificationMapper;
    
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public PageResult<NotificationVO> getNotificationList(String title, Integer type, Integer pageNum, Integer pageSize) {
        // 构建查询条件
        LambdaQueryWrapper<SysNotification> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysNotification::getStatus, 1); // 只查询已发布的通知
        
        if (StringUtils.hasText(title)) {
            queryWrapper.like(SysNotification::getTitle, title);
        }
        
        if (type != null) {
            queryWrapper.eq(SysNotification::getType, type);
        }
        
        queryWrapper.orderByDesc(SysNotification::getPublishTime);
        
        // 分页查询
        Page<SysNotification> page = new Page<>(pageNum, pageSize);
        Page<SysNotification> notificationPage = notificationMapper.selectPage(page, queryWrapper);
        
        // 转换为VO
        List<NotificationVO> voList = new ArrayList<>();
        if (notificationPage.getRecords() != null && !notificationPage.getRecords().isEmpty()) {
            // 获取所有发布人ID
            List<Long> publishUserIds = notificationPage.getRecords().stream()
                    .map(SysNotification::getPublishUserId)
                    .distinct()
                    .collect(Collectors.toList());
            
            // 查询所有发布人信息
            Map<Long, String> userMap = userMapper.selectList(
                    new LambdaQueryWrapper<SysUser>()
                            .in(SysUser::getId, publishUserIds)
            ).stream().collect(Collectors.toMap(
                    SysUser::getId,
                    user -> user.getRealName() != null ? user.getRealName() : user.getUsername()
            ));
            
            // 查询当前用户的已读状态
            Long currentUserId = SecurityUtil.getUserId();
            List<Long> notificationIds = notificationPage.getRecords().stream()
                    .map(SysNotification::getId)
                    .collect(Collectors.toList());
            
            Map<Long, Boolean> readStatusMap = userNotificationMapper.selectList(
                    new LambdaQueryWrapper<SysUserNotification>()
                            .eq(SysUserNotification::getUserId, currentUserId)
                            .in(SysUserNotification::getNotificationId, notificationIds)
            ).stream().collect(Collectors.toMap(
                    SysUserNotification::getNotificationId,
                    un -> un.getReadStatus() != null && un.getReadStatus() == 1
            ));
            
            // 转换为VO
            voList = notificationPage.getRecords().stream().map(notification -> {
                NotificationVO vo = new NotificationVO();
                BeanUtils.copyProperties(notification, vo);
                
                // 设置发布人姓名
                vo.setPublishUserName(userMap.getOrDefault(notification.getPublishUserId(), "未知"));
                
                // 设置已读状态
                vo.setIsRead(readStatusMap.getOrDefault(notification.getId(), false));
                
                // 格式化发布时间
                if (notification.getPublishTime() != null) {
                    vo.setPublishTime(notification.getPublishTime().format(DATE_FORMATTER));
                }
                
                return vo;
            }).collect(Collectors.toList());
        }
        
        return new PageResult<>(voList, notificationPage.getTotal(), pageNum, pageSize);
    }

    @Override
    public NotificationVO getNotificationById(Long id) {
        SysNotification notification = notificationMapper.selectById(id);
        if (notification == null) {
            throw new BusinessException("通知不存在");
        }
        
        NotificationVO vo = new NotificationVO();
        BeanUtils.copyProperties(notification, vo);
        
        // 查询发布人信息
        if (notification.getPublishUserId() != null) {
            SysUser user = userMapper.selectById(notification.getPublishUserId());
            if (user != null) {
                vo.setPublishUserName(user.getRealName() != null ? user.getRealName() : user.getUsername());
            }
        }
        
        // 查询当前用户的已读状态
        Long currentUserId = SecurityUtil.getUserId();
        SysUserNotification userNotification = userNotificationMapper.selectOne(
                new LambdaQueryWrapper<SysUserNotification>()
                        .eq(SysUserNotification::getUserId, currentUserId)
                        .eq(SysUserNotification::getNotificationId, id)
        );
        
        vo.setIsRead(userNotification != null && userNotification.getReadStatus() == 1);
        
        // 格式化发布时间
        if (notification.getPublishTime() != null) {
            vo.setPublishTime(notification.getPublishTime().format(DATE_FORMATTER));
        }
        
        // 自动标记为已读
        if (userNotification == null) {
            SysUserNotification newUserNotification = new SysUserNotification();
            newUserNotification.setUserId(currentUserId);
            newUserNotification.setNotificationId(id);
            newUserNotification.setReadStatus(1); // 已读
            newUserNotification.setReadTime(LocalDateTime.now());
            userNotificationMapper.insert(newUserNotification);
        } else if (userNotification.getReadStatus() == 0) {
            userNotification.setReadStatus(1);
            userNotification.setReadTime(LocalDateTime.now());
            userNotificationMapper.updateById(userNotification);
        }
        
        return vo;
    }
    
    @Override
    public Integer getUnreadCount() {
        Long currentUserId = SecurityUtil.getUserId();
        
        // 查询所有已发布的通知
        List<SysNotification> notifications = notificationMapper.selectList(
                new LambdaQueryWrapper<SysNotification>()
                        .eq(SysNotification::getStatus, 1)
        );
        
        if (notifications.isEmpty()) {
            return 0;
        }
        
        List<Long> notificationIds = notifications.stream()
                .map(SysNotification::getId)
                .collect(Collectors.toList());
        
        // 查询用户已读的通知
        List<Long> readNotificationIds = userNotificationMapper.selectList(
                new LambdaQueryWrapper<SysUserNotification>()
                        .eq(SysUserNotification::getUserId, currentUserId)
                        .eq(SysUserNotification::getReadStatus, 1) // 数据库中是1表示已读
                        .in(SysUserNotification::getNotificationId, notificationIds)
        ).stream().map(SysUserNotification::getNotificationId).collect(Collectors.toList());
        
        // 未读数量 = 总通知数 - 已读通知数
        return notifications.size() - readNotificationIds.size();
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void markAsRead(Long id) {
        // 检查通知是否存在
        SysNotification notification = notificationMapper.selectById(id);
        if (notification == null) {
            throw new BusinessException("通知不存在");
        }
        
        Long currentUserId = SecurityUtil.getUserId();
        
        // 查询用户通知关联
        SysUserNotification userNotification = userNotificationMapper.selectOne(
                new LambdaQueryWrapper<SysUserNotification>()
                        .eq(SysUserNotification::getUserId, currentUserId)
                        .eq(SysUserNotification::getNotificationId, id)
        );
        
        if (userNotification == null) {
            // 创建新的用户通知关联
            SysUserNotification newUserNotification = new SysUserNotification();
            newUserNotification.setUserId(currentUserId);
            newUserNotification.setNotificationId(id);
            newUserNotification.setReadStatus(1); // 已读
            newUserNotification.setReadTime(LocalDateTime.now());
            userNotificationMapper.insert(newUserNotification);
        } else if (userNotification.getReadStatus() == 0) {
            // 更新为已读
            userNotification.setReadStatus(1);
            userNotification.setReadTime(LocalDateTime.now());
            userNotificationMapper.updateById(userNotification);
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void markAllAsRead() {
        Long currentUserId = SecurityUtil.getUserId();
        
        // 查询所有已发布的通知
        List<SysNotification> notifications = notificationMapper.selectList(
                new LambdaQueryWrapper<SysNotification>()
                        .eq(SysNotification::getStatus, 1)
        );
        
        if (notifications.isEmpty()) {
            return;
        }
        
        List<Long> notificationIds = notifications.stream()
                .map(SysNotification::getId)
                .collect(Collectors.toList());
        
        // 查询用户已有的通知关联
        List<SysUserNotification> userNotifications = userNotificationMapper.selectList(
                new LambdaQueryWrapper<SysUserNotification>()
                        .eq(SysUserNotification::getUserId, currentUserId)
                        .in(SysUserNotification::getNotificationId, notificationIds)
        );
        
        Map<Long, SysUserNotification> userNotificationMap = userNotifications.stream()
                .collect(Collectors.toMap(SysUserNotification::getNotificationId, un -> un));
        
        LocalDateTime now = LocalDateTime.now();
        
        // 更新已有的通知关联为已读
        for (SysUserNotification un : userNotifications) {
            if (un.getReadStatus() == 0) {
                un.setReadStatus(1);
                un.setReadTime(now);
                userNotificationMapper.updateById(un);
            }
        }
        
        // 为没有关联的通知创建新的关联
        for (Long notificationId : notificationIds) {
            if (!userNotificationMap.containsKey(notificationId)) {
                SysUserNotification newUserNotification = new SysUserNotification();
                newUserNotification.setUserId(currentUserId);
                newUserNotification.setNotificationId(notificationId);
                newUserNotification.setReadStatus(1); // 已读
                newUserNotification.setReadTime(now);
                userNotificationMapper.insert(newUserNotification);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addNotification(SysNotification notification) {
        // 设置发布人ID和发布时间
        notification.setPublishUserId(SecurityUtil.getUserId());
        notification.setPublishTime(LocalDateTime.now());
        notification.setStatus(1); // 设置为已发布状态
        
        notificationMapper.insert(notification);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateNotification(SysNotification notification) {
        // 检查通知是否存在
        SysNotification existNotification = notificationMapper.selectById(notification.getId());
        if (existNotification == null) {
            throw new BusinessException("通知不存在");
        }
        
        // 只能修改自己发布的通知，管理员除外
        if (!SecurityUtil.isAdmin() && !existNotification.getPublishUserId().equals(SecurityUtil.getUserId())) {
            throw new BusinessException("无权修改他人发布的通知");
        }
        
        notificationMapper.updateById(notification);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteNotification(Long id) {
        // 检查通知是否存在
        SysNotification notification = notificationMapper.selectById(id);
        if (notification == null) {
            throw new BusinessException("通知不存在");
        }
        
        // 只能删除自己发布的通知，管理员除外
        if (!SecurityUtil.isAdmin() && !notification.getPublishUserId().equals(SecurityUtil.getUserId())) {
            throw new BusinessException("无权删除他人发布的通知");
        }
        
        // 删除用户通知关联
        userNotificationMapper.delete(
                new LambdaQueryWrapper<SysUserNotification>()
                        .eq(SysUserNotification::getNotificationId, id)
        );
        
        // 删除通知
        notificationMapper.deleteById(id);
    }
} 